package com.woniuxy.joylife.manager.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.common.constant.ManagerConstant;
import com.woniuxy.common.utils.KeyUtil;
import com.woniuxy.common.validate.AddGroup;
import com.woniuxy.common.validate.UpdateGroup;
import com.woniuxy.joylife.manager.VO.OwnerVO;
import com.woniuxy.joylife.manager.entity.OwnerEntity;
import com.woniuxy.joylife.manager.entity.OwnerRoomEntity;
import com.woniuxy.joylife.manager.service.OwnerRoomService;
import com.woniuxy.joylife.manager.service.OwnerService;
import com.woniuxy.joylife.manager.utils.PageUtils;
import com.woniuxy.joylife.manager.utils.R;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;


/**
 * @author renxiang
 * @email 981405195@qq.com
 * @date 2020-05-02 17:48:46
 */
@RestController
@RequestMapping("manager/owner")
public class OwnerController {
    @Autowired
    private OwnerService ownerService;

    @Autowired
    private OwnerRoomService ownerRoomService;

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    /**
     * 列表
     */
    @RequestMapping("/list")
    //@RequiresPermissions("manager:owner:list")
    public R list(@RequestParam Map<String, Object> params) {
        PageUtils page = ownerService.queryPage(params);
        return R.ok().put("page", page);
    }


    /**
     * 信息
     */
    @RequestMapping("/search/{name}")
    //@RequiresPermissions("manager:owner:info")
    public R search(@PathVariable("name") String name) throws Exception {
        // 模糊查询数据库
//        QueryChainWrapper<OwnerEntity> wraper = ownerService.query().like("name",name);
//        List<OwnerEntity> list = ownerService.list(wraper);
        // 从elasticsearch中读取数据
        if ("".equals(name) || name == null) {
            throw new Exception("name不能为空");
        }
        SearchRequest request = new SearchRequest("test_index");
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();

        // 精确查询
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", name);
        // 请求超时
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchSourceBuilder.query(termQueryBuilder);

        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red;'>");
        highlightBuilder.postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);

        request.source(searchSourceBuilder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        List<Map<String, Object>> list = new ArrayList<>();
        SearchHit[] hits = response.getHits().getHits();

        for (SearchHit h :
                hits) {
            HighlightField title = h.getHighlightFields().get("name");
            Map<String, Object> sourceAsMap = h.getSourceAsMap();
            if (title != null) {
                Text[] fragments = title.fragments();
                String newTitle = "";
                for (Text t :
                        fragments) {
                    newTitle += t;
                }
                sourceAsMap.put("name", newTitle);
            }
            list.add(sourceAsMap);
        }
        return R.ok().put("data", list);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    //@RequiresPermissions("manager:owner:save")
    public R save(@Validated({AddGroup.class}) @RequestBody OwnerVO ownerVO) throws Exception {
        OwnerEntity ownerEntity = new OwnerEntity();
        BeanUtils.copyProperties(ownerVO, ownerEntity);

        // 设置初始化参数
        ownerEntity.setOwnerId(KeyUtil.generateKey());
        ownerEntity.setCreatetime(new Date());
        ownerEntity.setState(ManagerConstant.UNDELETED);

        // 身份证、电话是否已经注册
        QueryWrapper<OwnerEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("phone", ownerEntity.getPhone()).or()
                .eq("id_card", ownerEntity.getIdCard())
                .eq("state",ManagerConstant.UNDELETED);
        OwnerEntity one = ownerService.getOne(wrapper);
        if (one == null) {

            // 插入elasticsearch
            if (addOne2ESindex(ownerEntity)) {
                throw new Exception("插入业主信息失败");
            }

            // 业主信息录入数据库
            ownerService.saveOwnerEntity(ownerEntity);

            // 存入居住信息表
            OwnerRoomEntity ownerRoomEntity = new OwnerRoomEntity();
            ownerRoomEntity.setOrId(KeyUtil.generateKey());
            ownerRoomEntity.setOwnerId(ownerEntity.getOwnerId());
            ownerRoomEntity.setBlocId(ownerVO.getBlockId());
            ownerRoomEntity.setUniId(ownerVO.getUnitId());
            ownerRoomEntity.setRoomId(ownerVO.getRoomId());
            ownerRoomEntity.setCreatetime(new Date());
            ownerRoomEntity.setState(ManagerConstant.UNDELETED);
            ownerRoomService.save(ownerRoomEntity);

            return R.ok();
        } else {
            return R.error(1, "添加失败,该用户已存在");
        }
    }

    // 添加一条数据到elasticsearch
    private Boolean addOne2ESindex(OwnerEntity ownerEntity) throws IOException {
        IndexRequest request = new IndexRequest("test_index");

        request.id(ownerEntity.getOwnerId());
        request.timeout(new TimeValue(1, TimeUnit.SECONDS));
        request.source(JSON.toJSONString(ownerEntity), XContentType.JSON);

        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        return response.getShardInfo().getFailed() == 0 ? false : true;
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    //@RequiresPermissions("manager:owner:update")
    public R update(@Validated({UpdateGroup.class}) @RequestBody OwnerVO ownerVO) throws Exception {

        OwnerEntity owner = new OwnerEntity();
        BeanUtils.copyProperties(ownerVO,owner);

        owner.setUpdatetime(new Date());

        // 更新居住信息
        if(!ownerRoomService.updateByAddress(ownerVO)){
            throw new Exception("修改业主信息失败,该房间已经被使用");
        }

        // 更新Elasticsearch
        if (updateES(owner)) {
            throw new Exception("修改业主信息失败");
        }

        ownerService.updateById(owner);


        return R.ok();
    }

    private Boolean updateES(OwnerEntity owner) throws IOException {
        UpdateRequest request = new UpdateRequest("test_index", owner.getOwnerId());
        request.timeout(new TimeValue(1, TimeUnit.SECONDS));
        request.doc(JSON.toJSONString(owner), XContentType.JSON);
        UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
        return update.getShardInfo().getFailed() == 0 ? false : true;
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    //@RequiresPermissions("manager:owner:delete")
    public R delete(@RequestBody String[] ownerIds) throws Exception {
        List<String> ownerIdsstrs = Arrays.asList(ownerIds);



        if (removeES(ownerIdsstrs)) {
            throw new Exception("删除业主信息失败");
        }
        boolean removeByIds = ownerService.removeByIds(ownerIdsstrs);
        if (removeByIds) return R.ok();
        else return R.error(1, "删除业主信息失败");
    }

    private Boolean removeES(List<String> ownerIdsstrs) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout(new TimeValue(60, TimeUnit.SECONDS));
        ownerIdsstrs.forEach(ownerid -> {
            bulkRequest.add(new DeleteRequest("test_index").id(ownerid));
        });
        BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        return response.hasFailures();
    }


}
